package com.wanlian.File;

import com.wanlian.encrypt.MD5Utils;
import com.wanlian.netty.model.NetFileInfoRecord;
import com.wanlian.util.DateUtil;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 文件操作类
 */
public class FileUtils {
    private static int page = 1024;
    private static int fileMaxSize = 64* 1024;

    /**
     * @param filePath 文件路径
     * @return 新文件
     * @Title: createNewFile1
     * @Description: 创建文件
     */
    public static File createNewFile(String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            boolean bresult = false;
            // 创建父文件夹
            String parentPath = file.getParent();
            File parentFile = new File(parentPath);
            if (!parentFile.exists()) {
                bresult = parentFile.mkdirs();
            } else {
                bresult = true;
            }
            if (bresult) {
                try {
                    // 创建新文件
                    bresult = file.createNewFile();
                    if (!bresult) {
                        return null;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                return null;
            }
        }
        return file;
    }

    /**
     * 删除单个文件
     *
     * @param filePath 要删除的文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String filePath) {
        File file = new File(filePath);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * 文件重命名
     *
     * @param oldpath
     * @param newPath
     * @return
     */
    public static boolean renameFile(String oldpath, String newPath) {
        if (!oldpath.equals(newPath)) {//新的文件名和以前文件名不同时,才有必要进行重命名
            File oldfile = new File(oldpath);
            File newfile = new File(newPath);
            if (!oldfile.exists()) {
                return false;//重命名文件不存在
            }
            if (newfile.exists())//若在该目录下已经有一个文件和新文件名相同，则不允许重命名
                System.out.println(newPath + "已经存在！");
            else {
                oldfile.renameTo(newfile);
                return true;
            }
        } else {
            System.out.println("新文件名和旧文件名相同");
        }
        return false;
    }


    /**
     * 判断文件是否存在
     *
     * @param filePath
     * @return
     */
    public static boolean isExist(String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            return false;
        }
        return true;
    }


    /**
     * @param filePath 文件路径
     * @return 新文件
     * @Title: createNewFile
     * @Description: 创建文件
     */
    public static boolean createNewFile(String filePath, boolean bRename) {
        File file = new File(filePath);
        if (!file.exists()) {
            boolean bresult = false;
            // 创建父文件夹
            String parentPath = file.getParent();
            File parentFile = new File(parentPath);
            if (!parentFile.exists()) {
                bresult = parentFile.mkdirs();
            } else {
                bresult = true;
            }
            if (bresult) {
                try {
                    // 创建新文件
                    bresult = file.createNewFile();
                    return bresult;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                return false;
            }
        } else {
            if (bRename == false) {
                return false;
            } else {
                boolean bresult = false;
                try {
                    bresult = file.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return bresult;
            }
        }
        return false;
    }

    /**
     * 通过byte数据创建新文件
     *
     * @param filePath
     * @param data
     * @param bRename
     * @return
     */
    public static boolean createNewFile(String filePath, byte[] data, boolean bRename) {
        File file = new File(filePath);
        if (!file.exists()) {
            boolean bresult = false;
            // 创建父文件夹
            String parentPath = file.getParent();
            File parentFile = new File(parentPath);
            if (!parentFile.exists()) {
                bresult = parentFile.mkdirs();
            } else {
                bresult = true;
            }
            if (bresult) {
                try {
                    FileOutputStream fos = null;
                    fos = new FileOutputStream(file);
                    fos.write(data, 0, data.length);
                    fos.flush();
                    fos.close();
                    return true;
                } catch (Exception e) {
                    e.printStackTrace();
                }

            } else {
                return false;
            }
        } else {
            if (bRename == false) {
                return false;
            } else {
                boolean bresult = false;
                try {
                    file.getName();
                    bresult = file.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return bresult;
            }
        }
        return false;
    }


    public static List<NetFileInfo> readFileByCurrentIndex(List<NetFileInfo> netFileInfos) {
        try {
            if (netFileInfos == null || netFileInfos.size() == 0) {
                return null;
            }
            File fileInfo = new File(netFileInfos.get(0).getFilePath());
            FileInputStream fs = new FileInputStream(fileInfo);
            List<NetFileInfo> newFileInfos = new ArrayList<>();
            for (NetFileInfo item : netFileInfos) {
                fs.skip(item.getCurrentIndex());
                long size = item.getSize();
                int i = 0;
                while (true) {
                    int leftSize = (int) (size - i * fileMaxSize);
                    if (leftSize <= fileMaxSize && leftSize > 0) {
                        byte[] bytes = new byte[leftSize];
                        fs.read(bytes, 0, leftSize);
                        NetFileInfo netFileInfo = new NetFileInfo();
                        netFileInfo.setFileName(fileInfo.getName());
                        netFileInfo.setTotalSize(fileInfo.length());
                        netFileInfo.setCurrentIndex(item.getCurrentIndex() + i * fileMaxSize);
                        netFileInfo.setBytes(bytes);
                        netFileInfo.setSize(leftSize);
                        newFileInfos.add(netFileInfo);
                        break;
                    } else {
                        byte[] bytes = new byte[fileMaxSize];
                        fs.read(bytes, 0, fileMaxSize);
                        NetFileInfo netFileInfo = new NetFileInfo();
                        netFileInfo.setFileName(fileInfo.getName());
                        netFileInfo.setTotalSize(fileInfo.length());
                        netFileInfo.setCurrentIndex(item.getCurrentIndex() + i * fileMaxSize);
                        netFileInfo.setBytes(bytes);
                        netFileInfo.setSize(fileMaxSize);
                        newFileInfos.add(netFileInfo);
                        i++;
                    }
                }
            }
            fs.close();
            return newFileInfos;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    public static void readFile(NetFileInfoRecord netFileInfoRecord) {
        try {
            if (netFileInfoRecord.bEnd) {
                return;
            }
            File fileInfo = new File(netFileInfoRecord.filePath);
            long currentIndex = netFileInfoRecord.currentIndex;
            netFileInfoRecord.totalSize = fileInfo.length();
            if (fileInfo.length() - currentIndex > page * fileMaxSize) {
                FileInputStream fs = new FileInputStream(fileInfo);
                fs.skip(currentIndex);
                byte[] bytes = new byte[page * fileMaxSize];
                fs.read(bytes, 0, page * fileMaxSize);
                fs.close();
                for (int i = 0; i < page; i++) {
                    NetFileInfo netFileInfo = new NetFileInfo();
                    netFileInfo.setFileName(fileInfo.getName());
                    netFileInfo.setFilePath(fileInfo.getPath());
                    netFileInfo.setTotalSize(fileInfo.length());
                    netFileInfo.setCurrentIndex(currentIndex + i * fileMaxSize);
                    byte[] fileBytes = new byte[fileMaxSize];
                    System.arraycopy(bytes, i * fileMaxSize, fileBytes, 0, fileMaxSize);
                    netFileInfo.setBytes(fileBytes);
                    netFileInfo.setSize(fileMaxSize);
                    netFileInfoRecord.currentIndex += fileMaxSize;
                    netFileInfoRecord.add(netFileInfo);
                }
            } else {
                int size = (int) (fileInfo.length() - currentIndex);
                FileInputStream fs = new FileInputStream(fileInfo);
                fs.skip(currentIndex);
                byte[] bytes = new byte[size];
                fs.read(bytes, 0, size);
                fs.close();
                int i = 0;
                while (true) {
                    if (size - i * fileMaxSize < fileMaxSize) {
                        int leftsize = size - i * fileMaxSize;
                        NetFileInfo netFileInfo = new NetFileInfo();
                        netFileInfo.setFileName(fileInfo.getName());
                        //netFileInfo.setFilePath(fileInfo.getPath());
                        netFileInfo.setTotalSize(fileInfo.length());
                        netFileInfo.setCurrentIndex(currentIndex + i * fileMaxSize);
                        byte[] leftBytes = new byte[leftsize];
                        System.arraycopy(bytes, i * fileMaxSize, leftBytes, 0, leftsize);
                        netFileInfo.setBytes(leftBytes);
                        netFileInfo.setSize(leftsize);
                        netFileInfoRecord.add(netFileInfo);
                        netFileInfoRecord.currentIndex += leftsize;
                        netFileInfoRecord.bEnd = true;
                        break;
                    } else {
                        NetFileInfo netFileInfo = new NetFileInfo();
                        netFileInfo.setFileName(fileInfo.getName());
                        netFileInfo.setTotalSize(fileInfo.length());
                        netFileInfo.setCurrentIndex(currentIndex + i * fileMaxSize);

                        byte[] fileBytes = new byte[fileMaxSize];
                        System.arraycopy(bytes, i * fileMaxSize, fileBytes, 0, fileMaxSize);
                        netFileInfo.setBytes(fileBytes);
                        netFileInfoRecord.currentIndex += fileMaxSize;
                        netFileInfo.setSize(fileMaxSize);
                        netFileInfoRecord.add(netFileInfo);
                        i++;
                    }
                }
            }
        } catch (Exception e) {

        }
    }


    public static NetFileInfo readFile(String filepath, long currentIndex) {
        try {
            File file = new File(filepath);
            NetFileInfo netFileInfo = new NetFileInfo();
            netFileInfo.setFileName(file.getName());
            netFileInfo.setTotalSize(file.length());
            netFileInfo.setCurrentIndex(currentIndex);
            FileInputStream inputStream = new FileInputStream(filepath);
            inputStream.skip(currentIndex);
            if (file.length() - netFileInfo.getCurrentIndex() > fileMaxSize) {
                int size = fileMaxSize;
                byte[] buffer = new byte[size];

                inputStream.read(buffer, 0, buffer.length);
                inputStream.close();
                netFileInfo.setSize(size);
                netFileInfo.setBytes(buffer);
            } else {
                int size = (int) (file.length() - currentIndex);
                byte[] buffer = new byte[size];
                inputStream.read(buffer, 0, buffer.length);
                inputStream.close();
                netFileInfo.setSize(size);
                netFileInfo.setBytes(buffer);
            }
            return netFileInfo;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void writeFile(NetFileInfo netFileInfo) {
        try {
            String path = netFileInfo.getFilePath();
            File file = new File(path);
            if (!file.exists()) {
                file.createNewFile();
            }
            FileOutputStream outputStream = new FileOutputStream(path, true);
            byte[] buffer = netFileInfo.getBytes();
            outputStream.write(buffer, (int)netFileInfo.getCurrentIndex(), buffer.length);
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //public static void writeFile


    /**
     * 获取云盘子项目
     *
     * @param dirPath
     * @return
     */
    public static List<StorageItem> getStorageItemsByDir(String dirPath) {
        List<StorageItem> items = new ArrayList<>();
        File file = new File(dirPath);
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File fileItem : files) {
                //如果这个文件是目录，则进行递归搜索
                if (!fileItem.isDirectory()) {
                    StorageItem storageItem = new StorageItem(fileItem);
                    items.add(storageItem);
                }
            }
        }
        return items;
    }

    public static List<DateStorageItem> getDateStorageItem(String path) {
        List<StorageItem> items = getStorageItemsByDir(path);
        Collections.sort(items, new Comparator<StorageItem>() {
            @Override
            public int compare(StorageItem o1, StorageItem o2) {
                if (o1.getUploadTime().getTime() > o2.getUploadTime().getTime()) {
                    return 1;
                } else {
                    return -1;
                }
            }
        });
//        Map<String, List<StorageItem>> maps = new HashMap<>();
//        for (StorageItem item : items) {
//            String date = DateUtil.getDataByTimestamp(item.getUploadTime());
//            if (maps.containsKey(date)) {
//                maps.get(date).add(item);
//            } else {
//                List<StorageItem> nitems = new ArrayList<>();
//                nitems.add(item);
//                maps.put(date, nitems);
//            }
//        }
        List<DateStorageItem> dateStorageItems = new ArrayList<>();
        for (StorageItem item : items) {
            String date = DateUtil.getDataByTimestamp(item.getUploadTime());
            DateStorageItem dateStorageItem = findByDate(date, dateStorageItems);
            if (dateStorageItem != null) {
                dateStorageItem.setDate(date);
                dateStorageItem.getItems().add(item);
            } else {
                dateStorageItem = new DateStorageItem();
                dateStorageItem.setDate(date);
                dateStorageItem.setItems(new ArrayList<>());
                dateStorageItem.getItems().add(item);
                dateStorageItems.add(dateStorageItem);
            }
        }
        return dateStorageItems;
    }


    private static DateStorageItem findByDate(String date, List<DateStorageItem> dateStorageItems) {
        for (DateStorageItem item : dateStorageItems) {
            if (item.getDate().equals(date)) {
                return item;
            }
        }
        return null;
    }

    public static String getMD5(File file) {
        FileInputStream fileInputStream = null;
        try {
            MessageDigest MD5 = MessageDigest.getInstance("MD5");
            fileInputStream = new FileInputStream(file);
            byte[] buffer = new byte[8192];
            int length;
            while ((length = fileInputStream.read(buffer)) != -1) {
                MD5.update(buffer, 0, length);
            }
            return new String(Hex.encodeHex(MD5.digest()));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 求一个字符串的md5值
     *
     * @param target 字符串
     * @return md5 value
     */
    public static String MD5(String target) {
        return DigestUtils.md5Hex(target);
    }

    public static void main(String[] args) throws InterruptedException {
        System.out.println(System.currentTimeMillis());

        String str1 = "78:A3:51:5B:E8:78";
        //String str2 = "78:A3:51:00:01:02";

        System.out.println(MD5Utils.MD5Encode(str1, "utf-8"));
        //System.out.println(MD5Utils.MD5Encode(str2, "utf-8"));

        //  NetFileInfo netFileInfo=new NetFileInfo();
//        String filePath="D:\\holl7\\work\\project\\wanlian\\gitee\\net_project\\WindowsFormsApp1\\WindowsFormsApp1\\bin\\Debug.rar";
//        while(true) {
//            netFileInfo =FileUtils.readFile(filePath,netFileInfo.getCurrentIndex());
//            FileUtils.writeFile(netFileInfo);
//            if(netFileInfo.getCurrentIndex()==netFileInfo.getTotalsize()){
//                break;
//            }
//            Thread.sleep(200);
//        }
//        System.out.println("文件复制完成");
        //System.out.println(JsonStringUtil.writeValueAsString(FileUtils.getDateStorageItem("C:\\holly7\\files\\photo")));


//        long beginTime = System.currentTimeMillis();
//        File file = new File("C:\\holly7\\files\\FirmWare_1.0.4_20181107.bin");
//        String md5 = getMD5(file);
//        long endTime = System.currentTimeMillis();
//        System.out.println("MD5:" + md5 + "\n 耗时:" + ((endTime - beginTime) / 1000) + "s");
        //FileUtils.renameFile("C:\\holly7\\files\\photo\\1.txt","C:\\holly7\\files\\photo\\2.txt");
    }

}
